// services/subscription.service.js
const { logInfo, logError, logWarning } = require('../logger');
const { Sequelize } = require('sequelize');

// 数据模型
const Subscription = require('../models/Subscription');
const SubscriptionPlan = require('../models/SubscriptionPlan');

// 数据库模型
const { UserSubscription } = require('../models/User');

class SubscriptionService {
  /**
   * 获取所有订阅计划
   * @returns {Array} 订阅计划列表
   */
  async getSubscriptionPlans() {
    try {
      // 返回硬编码的订阅计划（在实际应用中应从数据库获取）
      const plans = [
        new SubscriptionPlan({
          id: 'monthly',
          name: 'monthly',
          displayName: '月度会员',
          price: 1800, // 单位：分
          currency: 'CNY',
          durationDays: 30,
          features: [
            '无限制测算工具使用',
            '专属解梦服务',
            '优先客服支持'
          ],
          isPopular: false,
          isActive: true,
          sortOrder: 1
        }),
        new SubscriptionPlan({
          id: 'quarterly',
          name: 'quarterly',
          displayName: '季度会员',
          price: 4800,
          currency: 'CNY',
          durationDays: 90,
          features: [
            '无限制测算工具使用',
            '专属解梦服务',
            '优先客服支持',
            '月度运势报告'
          ],
          isPopular: false,
          isActive: true,
          sortOrder: 2
        }),
        new SubscriptionPlan({
          id: 'yearly',
          name: 'yearly',
          displayName: '年度会员',
          price: 9800,
          currency: 'CNY',
          durationDays: 365,
          features: [
            '无限制测算工具使用',
            '专属解梦服务',
            '优先客服支持',
            '月度运势报告',
            '年度运势大礼包',
            '免费线下活动参与资格'
          ],
          isPopular: true,
          isActive: true,
          sortOrder: 3
        })
      ];

      logInfo('获取订阅计划成功', { count: plans.length });
      return plans;
    } catch (error) {
      logError('获取订阅计划失败', { error: error.message, stack: error.stack });
      throw new Error('获取订阅计划失败');
    }
  }

  /**
   * 为用户创建订阅
   * @param {Object} subscriptionData - 订阅数据
   * @param {string} subscriptionData.userId - 用户ID
   * @param {string} subscriptionData.planId - 计划ID
   * @returns {Subscription} 订阅对象
   */
  async createSubscription(subscriptionData) {
    try {
      const { userId, planId } = subscriptionData;

      // 检查用户是否已有有效订阅
      const existingSubscription = await this.getActiveSubscription(userId);
      if (existingSubscription) {
        logWarning('用户已有有效订阅', { userId, subscriptionId: existingSubscription.id });
        throw new Error('用户已有有效订阅');
      }

      // 获取订阅计划
      const plans = await this.getSubscriptionPlans();
      const plan = plans.find(p => p.id === planId);
      
      if (!plan) {
        logWarning('订阅计划不存在', { planId });
        throw new Error('订阅计划不存在');
      }

      // 计算订阅时间
      const startDate = new Date();
      const endDate = new Date(startDate);
      endDate.setDate(startDate.getDate() + plan.durationDays);

      // 创建订阅记录
      const subscription = new Subscription({
        id: this.generateSubscriptionId(),
        userId,
        planId,
        status: 'active',
        startDate: startDate.toISOString(),
        endDate: endDate.toISOString(),
        autoRenew: true, // 默认自动续订
        createdAt: new Date(),
        updatedAt: new Date()
      });

      // 保存订阅到数据库
      await this.saveSubscription(subscription);

      logInfo('订阅创建成功', { subscriptionId: subscription.id, userId, planId });
      return subscription;
    } catch (error) {
      logError('创建订阅失败', { 
        userId: subscriptionData.userId, 
        planId: subscriptionData.planId, 
        error: error.message,
        stack: error.stack
      });
      throw new Error(error.message || '创建订阅失败');
    }
  }

  /**
   * 生成订阅ID
   * @returns {string} 订阅ID
   */
  generateSubscriptionId() {
    // 生成唯一订阅ID：时间戳+随机数
    return `SUB_${Date.now()}_${Math.random().toString(36).substr(2, 9).toUpperCase()}`;
  }

  /**
   * 保存订阅到数据库
   * @param {Subscription} subscription - 订阅对象
   */
  async saveSubscription(subscription) {
    await UserSubscription.create({
      id: subscription.id,
      userId: subscription.userId,
      planId: subscription.planId,
      status: subscription.status,
      startDate: subscription.startDate,
      endDate: subscription.endDate,
      autoRenew: subscription.autoRenew,
      transactionId: subscription.transactionId || null,
      createdAt: subscription.createdAt,
      updatedAt: subscription.updatedAt
    });
  }

  /**
   * 获取用户当前有效订阅
   * @param {string} userId - 用户ID
   * @returns {Subscription|null} 订阅对象
   */
  async getActiveSubscription(userId) {
    try {
      // 获取当前时间
      const now = new Date();
      
      // 查询用户的有效订阅（状态为active且结束时间大于当前时间）
      const subscription = await UserSubscription.findOne({
        where: {
          userId: userId,
          status: 'active',
          endDate: {
            [Sequelize.Op.gt]: now
          }
        },
        order: [['createdAt', 'DESC']]
      });

      return subscription ? subscription.toJSON() : null;
    } catch (error) {
      logError('获取用户有效订阅失败', { userId, error: error.message });
      throw new Error('获取用户订阅信息失败');
    }
  }

  /**
   * 获取用户所有订阅记录
   * @param {string} userId - 用户ID
   * @returns {Array} 订阅列表
   */
  async getUserSubscriptions(userId) {
    try {
      const subscriptions = await UserSubscription.findAll({
        where: {
          userId: userId
        },
        order: [['createdAt', 'DESC']]
      });

      return subscriptions.map(sub => sub.toJSON());
    } catch (error) {
      logError('获取用户订阅记录失败', { userId, error: error.message });
      throw new Error('获取用户订阅记录失败');
    }
  }

  /**
   * 取消订阅
   * @param {string} subscriptionId - 订阅ID
   * @param {string} userId - 用户ID
   * @returns {boolean} 是否成功
   */
  async cancelSubscription(subscriptionId, userId) {
    try {
      // 验证订阅属于该用户
      const subscription = await this.getUserSubscriptionById(subscriptionId);
      if (!subscription || subscription.userId !== userId) {
        logWarning('订阅不属于该用户', { subscriptionId, userId });
        throw new Error('订阅不存在或无权限操作');
      }

      // 检查订阅状态
      if (subscription.status !== 'active') {
        logWarning('订阅状态不允许取消', { subscriptionId, status: subscription.status });
        throw new Error('订阅状态不允许取消');
      }

      // 更新订阅状态
      await UserSubscription.update({
        status: 'cancelled',
        updatedAt: new Date()
      }, {
        where: {
          id: subscriptionId
        }
      });

      logInfo('订阅取消成功', { subscriptionId, userId });
      return true;
    } catch (error) {
      logError('取消订阅失败', { 
        subscriptionId, 
        userId, 
        error: error.message,
        stack: error.stack
      });
      throw new Error(error.message || '取消订阅失败');
    }
  }

  /**
   * 根据ID获取用户订阅
   * @param {string} subscriptionId - 订阅ID
   * @returns {Subscription|null} 订阅对象
   */
  async getUserSubscriptionById(subscriptionId) {
    try {
      const subscription = await UserSubscription.findByPk(subscriptionId);
      return subscription ? subscription.toJSON() : null;
    } catch (error) {
      logError('获取订阅失败', { subscriptionId, error: error.message });
      throw new Error('获取订阅失败');
    }
  }

  /**
   * 检查用户是否为VIP
   * @param {string} userId - 用户ID
   * @returns {boolean} 是否为VIP
   */
  async isUserVip(userId) {
    try {
      // 获取当前时间
      const now = new Date();
      
      // 查询用户的有效订阅
      const activeSubscription = await UserSubscription.findOne({
        where: {
          userId: userId,
          status: 'active',
          endDate: {
            [Sequelize.Op.gt]: now
          }
        },
        limit: 1
      });

      return !!activeSubscription;
    } catch (error) {
      logError('检查VIP状态失败', { userId, error: error.message });
      return false;
    }
  }

  /**
   * 获取订阅详情（包含计划信息）
   * @param {string} subscriptionId - 订阅ID
   * @returns {Object} 订阅详情
   */
  async getSubscriptionDetails(subscriptionId) {
    try {
      const subscription = await this.getUserSubscriptionById(subscriptionId);
      if (!subscription) {
        throw new Error('订阅不存在');
      }

      // 获取订阅计划详情
      const plans = await this.getSubscriptionPlans();
      const plan = plans.find(p => p.id === subscription.planId);

      return {
        ...subscription,
        plan: plan || null
      };
    } catch (error) {
      logError('获取订阅详情失败', { subscriptionId, error: error.message });
      throw new Error('获取订阅详情失败');
    }
  }
}

module.exports = SubscriptionService;